home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / minix / up1510b.tgz / up1510b / src / commands / cron.c < prev    next >
C/C++ Source or Header  |  1990-07-23  |  7KB  |  306 lines

  1. /* Cron - clock daemon            Author: S.R. Sampson */
  2.  
  3. /*    Cron is the clock daemon.  It is typically started up from the
  4.  *    /etc/rc file by the line:
  5.  *        /usr/bin/cron
  6.  *    Cron automatically puts itself in the background, so no & is needed.
  7.  *    If cron is used, it runs all day, spending most of its time asleep.
  8.  *    Once a minute it wakes up and examines /usr/lib/crontab to see if there
  9.  *    are any commands to be executed.  The format of this table is the same
  10.  *    as in UNIX, except that % is not allowed to indicate 'new line.'
  11.  *
  12.  *    Each crontab entry has six fields:
  13.  *       minute    hour  day-of-the-month  month  day-of-the-week  command
  14.  *    Each entry is checked in turn, and any entry matching the current time
  15.  *    is executed.  The entry * matches anything.  Some examples:
  16.  *
  17.  *   min hr dat mo day   command
  18.  *    *  *   *  *   *    /usr/bin/date >/dev/tty0   #print date every minute
  19.  *    0  *   *  *   *    /usr/bin/date >/dev/tty0   #print date on the hour
  20.  *   30  4   *  *  1-5   /bin/backup /dev/fd1       #do backup Mon-Fri at 0430
  21.  *   30 19   *  *  1,3,5 /etc/backup /dev/fd1       #Mon, Wed, Fri at 1930
  22.  *    0  9  25 12   *    /usr/bin/sing >/dev/tty0   #Xmas morning at 0900 only
  23.  *
  24.  * Version 1.6  SrT  90/04/08
  25.  *      Added casting fixes by Ralf Wenk, and integrated net
  26.  *      changes that release current directory, and use the
  27.  *      1.5.5 include files.  Altered assign, so no temporary
  28.  *    buffer is needed.
  29.  *
  30.  * Version 1.5  SrT  89/04/10
  31.  *    Changed sleep code, to type SRS sent me.
  32.  *
  33.  * Version 1.4  SrT  89/03/17
  34.  *    Fixed a pointer problem, when reloading crontab.
  35.  *
  36.  * Version 1.3  SrT  89/03/16
  37.  *    Loads crontab, into memory and only rereads the disk
  38.  *    version if it changes.  (Free up those clock cycles!)
  39.  *
  40.  * Fixed 03/10/89, by Simmule Turner, simmy@nu.cs.fsu.edu
  41.  *    Now correctly cleans up zombie processes
  42.  *    Logs actions to /usr/adm/cronlog
  43.  *    Syncs with clock after each minute
  44.  *    Comments allowed in crontab
  45.  *    Fixed bug that prevented month, from matching
  46. */
  47.  
  48.  
  49. #include <sys/types.h>
  50. #include <sys/stat.h>
  51. #include <signal.h>
  52. #include <time.h>
  53. #include <string.h>
  54. #include <fcntl.h>
  55. #include <stdio.h>
  56.  
  57. #ifndef DEBUG
  58. #define CRONTAB "/usr/lib/crontab"
  59. #define LOGFILE "/usr/adm/cronlog"
  60. #else
  61. #define LOGFILE "/usr/adm/cronlog.dbg"
  62. #define CRONTAB "/usr/adm/crontab.dbg"
  63. #endif
  64.  
  65. #define NULLDEV "/dev/null"
  66. #define SEPARATOR " \t"
  67. #define CRONSIZE  2048
  68. #define CRONSTRUCT struct cron_entry
  69.  
  70. #define    TRUE    1
  71. #define    FALSE    0
  72.  
  73. struct cron_entry {
  74.   char *mn;
  75.   char *hr;
  76.   char *day;
  77.   char *mon;
  78.   char *wkd;
  79.   char *cmd;
  80.   struct cron_entry *next;
  81. } *head, *entry_ptr;
  82.  
  83. char crontab[CRONSIZE];
  84. FILE *cronlog;
  85.  
  86. int wakeup(), ret();
  87.  
  88. time_t previous_time = 0L;
  89.  
  90. main()
  91. {
  92.   int status;
  93.   time_t clock;
  94.  
  95.   status = fork();
  96.   if (status == -1) {
  97.     fprintf(stderr, "Can't fork cron\n");
  98.     exit(1);
  99.   }
  100.  
  101.   if (status > 0) exit(0);
  102.  
  103.   signal(SIGINT, SIG_IGN);
  104.   signal(SIGHUP, SIG_IGN);
  105.   signal(SIGQUIT, SIG_IGN);
  106.  
  107.   close(0);
  108.   close(1);
  109.   close(2);
  110.  
  111.   chdir("/");
  112.  
  113.   open(NULLDEV, O_RDONLY);
  114.   if ((cronlog = fopen(LOGFILE, "a")) == (FILE *) NULL) {
  115.     open(NULLDEV, O_WRONLY);
  116.     open(NULLDEV, O_WRONLY);
  117.   } else {
  118.     setbuf(cronlog, (char *) NULL);
  119.     dup(fileno(cronlog));
  120.   }
  121.  
  122.   entry_ptr = (CRONSTRUCT *) malloc(sizeof(CRONSTRUCT));
  123.   entry_ptr->next = (CRONSTRUCT *) NULL;
  124.   head = entry_ptr;
  125.  
  126.   while (TRUE) {
  127.     signal(SIGALRM, wakeup);
  128.     time(&clock);
  129.     alarm((unsigned) (60 - clock % 60));
  130.     pause();
  131.  
  132.     signal(SIGALRM, ret);
  133.     alarm(1);
  134.     while (wait((int *) NULL) != (-1));
  135.   }
  136. }
  137.  
  138. int ret() {}
  139.  
  140. wakeup()
  141. {
  142.   register struct tm *tm;
  143.   time_t cur_time;
  144.   CRONSTRUCT *this_entry = head;
  145.  
  146.   load_crontab();
  147.  
  148.   time(&cur_time);
  149.   tm = localtime(&cur_time);
  150.  
  151.   while (this_entry->next && this_entry->mn) {
  152.     if (match(this_entry->mn, tm->tm_min) &&
  153.         match(this_entry->hr, tm->tm_hour) &&
  154.         match(this_entry->day, tm->tm_mday) &&
  155.         match(this_entry->mon, tm->tm_mon + 1) &&
  156.         match(this_entry->wkd, tm->tm_wday)) {
  157.         fprintf(cronlog, "%02d/%02d-%02d:%02d  %s\n",
  158.             tm->tm_mon + 1, tm->tm_mday, tm->tm_hour,
  159.             tm->tm_min, this_entry->cmd);
  160.         if (fork() == 0) {
  161.             execl("/bin/sh", "/bin/sh", "-c",
  162.                           this_entry->cmd, (char *) 0);
  163.             exit(1);
  164.         }
  165.     }
  166.     this_entry = this_entry->next;
  167.   }
  168. }
  169.  
  170. /*
  171.  *    This routine will match the left string with the right number.
  172.  *
  173.  *    The string can contain the following syntax *
  174.  *    *        This will return TRUE for any number
  175.  *    x,y [,z, ...]    This will return TRUE for any number given.
  176.  *    x-y        This will return TRUE for any number within
  177.  *            the range of x thru y.
  178.  */
  179.  
  180. match(left, right)
  181. register char *left;
  182. register int right;
  183. {
  184.   register int n;
  185.   register char c;
  186.  
  187.   n = 0;
  188.   if (!strcmp(left, "*")) return(TRUE);
  189.  
  190.   while ((c = *left++) && (c >= '0') && (c <= '9')) n = (n * 10) + c - '0';
  191.  
  192.   switch (c) {
  193.       case '\0':
  194.     return(right == n);
  195.  
  196.       case ',':
  197.     if (right == n) return(TRUE);
  198.     do {
  199.         n = 0;
  200.         while ((c = *left++) && (c >= '0') && (c <= '9'))
  201.             n = (n * 10) + c - '0';
  202.  
  203.         if (right == n) return(TRUE);
  204.     } while (c == ',');
  205.     return(FALSE);
  206.  
  207.       case '-':
  208.     if (right < n) return(FALSE);
  209.  
  210.     n = 0;
  211.     while ((c = *left++) && (c >= '0') && (c <= '9'))
  212.         n = (n * 10) + c - '0';
  213.  
  214.     return(right <= n);
  215.   }
  216. }
  217.  
  218. load_crontab()
  219. {
  220.   int pos = 0;
  221.   FILE *cfp;
  222.   struct stat buf;
  223.  
  224.   if (stat(CRONTAB, &buf)) {
  225.     if (previous_time == 0L) printf("Can't stat crontab\n");
  226.     previous_time = 0L;
  227.     return;
  228.   }
  229. #ifdef DEBUG
  230.   printf("Crontab Time:%ld In_Core:%ld\n", buf.st_mtime, previous_time);
  231. #endif
  232.  
  233.   if (buf.st_mtime <= previous_time) return;
  234.  
  235.   if ((cfp = fopen(CRONTAB, "r")) == (FILE *) NULL) {
  236.     if (previous_time == 0L) printf("Can't open crontab\n");
  237.     previous_time = 0L;
  238.     return;
  239.   }
  240.   previous_time = buf.st_mtime;
  241.  
  242.   entry_ptr = head;
  243.   while (fgets(&crontab[pos], CRONSIZE - pos, cfp) != (char *) NULL) {
  244.     int len;
  245.  
  246.     if (crontab[pos] == '#') continue;
  247.     len = strlen(&crontab[pos]);
  248.     if (crontab[pos + len - 1] == '\n') {
  249.         len--;
  250.         crontab[pos + len] = '\0';
  251.     }
  252.     assign(entry_ptr, &crontab[pos]);
  253.     if (entry_ptr->next == (CRONSTRUCT *) NULL) {
  254.         entry_ptr->next = (CRONSTRUCT *) malloc(sizeof(CRONSTRUCT));
  255.         entry_ptr->next->next = (CRONSTRUCT *) NULL;
  256.     }
  257.     entry_ptr = entry_ptr->next;
  258.     pos += ++len;
  259.     if (pos >= CRONSIZE) break;
  260.   }
  261.   fclose(cfp);
  262.  
  263.   while (entry_ptr) {
  264.     entry_ptr->mn = (char *) NULL;
  265.     entry_ptr = entry_ptr->next;
  266.   }
  267.  
  268. #ifdef DEBUG
  269.   printf("Crontab uses %d/%d bytes\n", pos, CRONSIZE);
  270.   {
  271.     CRONSTRUCT *start = head;
  272.     dumptable(start);
  273.   }
  274. #endif
  275. }
  276.  
  277. assign(entry, line)
  278. CRONSTRUCT *entry;
  279. char *line;
  280. {
  281.   entry->mn = strtok(line, SEPARATOR);
  282.   entry->hr = strtok((char *) NULL, SEPARATOR);
  283.   entry->day = strtok((char *) NULL, SEPARATOR);
  284.   entry->mon = strtok((char *) NULL, SEPARATOR);
  285.   entry->wkd = strtok((char *) NULL, SEPARATOR);
  286.   entry->cmd = strchr(entry->wkd,'\0') + 1;
  287. }
  288.  
  289. #ifdef DEBUG
  290. dumptable(table)
  291. CRONSTRUCT *table;
  292. {
  293.   time_t clock;
  294.   time(&clock);
  295.  
  296.   printf("\nContents of crontab at: %s", ctime(&clock));
  297.   printf("Minute\tHour\tDay\tMonth\tWeekday\tCommand\n");
  298.   while (table->next && table->mn) {
  299.     printf("%s\t%s\t%s\t%s\t%s\t%s\n",
  300.            table->mn, table->hr, table->day, table->mon,
  301.            table->wkd, table->cmd);
  302.     table = table->next;
  303.   }
  304. }
  305. #endif
  306.